package dead.queue.mt.demo.message;


import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import dead.queue.mt.demo.entity.MessageInfo;
import dead.queue.mt.demo.entity.MessageNameConfig;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Component
public class MessageReceiver {

    @Autowired
    RedisTemplate  redisTemplate;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /**
     * mt队列消费
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(queues = MessageNameConfig.testQueueName, concurrency = "1")
    public void receiveMessage(Message message, Channel channel) throws IOException {

        try {
            System.out.println("mt接收到消息。");

            //触发异常
            int[] arrays = {1};
            int aa = arrays[10];

            //手动ack
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception ex) {
            //接收消息体
            ObjectMapper mapper = new ObjectMapper();
            MessageInfo messageInfo = mapper.readValue(message.getBody(), MessageInfo.class);

            int retryCount = 0;

            //通过msgId从redis获取次数
            Object count = stringRedisTemplate.opsForValue().get(messageInfo.getMsgId());
            if(count != null) {
                retryCount = Integer.parseInt(count+"");
            }

            System.out.println("msgId：" + messageInfo.getMsgId() + "，重试次数retryCount : " + retryCount);

            if (retryCount >= 3) {
                //重试超过3次进入死信队列
                //requeue = false 放入死信队列
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
            } else {
                //重试次数不超过3次，重新放入队列，重试消息
                //requeue = true 放入消费队列重试消费
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);

                //重试次数+1,存入redis，并设置超过时间（实际以项目情况为准）
                stringRedisTemplate.opsForValue().set(messageInfo.getMsgId(), retryCount+1+"",5, TimeUnit.MINUTES);
            }
        }
    }

    /**
     * 死信队列消费方法
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(queues = MessageNameConfig.testDeadLetterQueueName)
    public void process(Message message, Channel channel) throws IOException {
        System.out.println("mt收到进入死信队列消息");

        //触发钉钉告警
        System.out.println("触发钉钉告警");

        //写入死信消息写入数据库
        System.out.println("死信消息写入数据库");

        //确认消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }


}
